package com.content.scaffold.common.utils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaojl
 */
public class SerialNumberUtils {

    public static String getBatchNoV2(String notaryOfficeId) {
        // 使用线程安全的时间格式化工具
        String formatted = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));

        // 安全获取后两位年份
        String yearSuffix = formatted.length() >= 2 ? formatted.substring(formatted.length() - 2) : formatted;

        // 构建 Redis Key
        String lockKey = "lock:getBatchNum:" + notaryOfficeId + formatted;

        // 获取 RedisTemplate 实例
        RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringContextHolder.getBean("redisTemplate");

        // 定义 Lua 脚本
        String script = "local currentVal = redis.call('GET', KEYS[1])\n" +
                "if currentVal == false then\n" +
                "   redis.call('SET', KEYS[1], 1)\n" +
                "   redis.call('EXPIRE', KEYS[1], ARGV[1])\n" +
                "   return 1\n" +
                "elseif string.match(currentVal, '^%d+$') then\n" +
                "   return redis.call('INCR', KEYS[1])\n" +
                "else\n" +
                "   return redis.error_reply('Value is not an integer or out of range')\n" +
                "end";

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);

        // 执行脚本
        Long incr = redisTemplate.execute(redisScript, List.of(lockKey), String.valueOf(TimeUnit.DAYS.toSeconds(366)));

        if (incr == null || incr <= 0) {
            throw new RuntimeException("Failed to generate batch number");
        }

        // 安全获取机构 ID 后两位
        String officeIdSuffix = notaryOfficeId.length() >= 2 ?
                notaryOfficeId.substring(notaryOfficeId.length() - 2) :
                String.format("%02d", Math.max(0, Integer.parseInt(notaryOfficeId) % 100));

        String orderNum = String.format("%08d", incr);

        return yearSuffix +
                officeIdSuffix +
                orderNum;
    }

}
